#include "DirectXStuff.h"
#include "World.h"
#include "MatrixStack.h"

LPDIRECT3D9             g_pD3D = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // Our rendering device
LPD3DXEFFECT			g_CubeShader = NULL; //=== OUR SHADER EFFECT:
D3DXMATRIX				g_WorldViewProj; //Global Matrix
LPD3DXFONT				g_font = NULL;	// Stores the font (duh)

D3DXFONT_DESC FONTDESC =
	{
		22,
		0,
		400,
		0,
		false,
		DEFAULT_CHARSET,
		OUT_TT_PRECIS,
		CLIP_DEFAULT_PRECIS,
		DEFAULT_PITCH,
		0//L"Lucida Calligraphy"
	};

//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Initializes Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
    // Create the D3D object.
    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;

    // Set up the structure used to create the D3DDevice
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof( d3dpp ) );
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

    // Create the D3DDevice
    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_pd3dDevice ) ) )
    {
        return E_FAIL;
    }

    // Device state would normally be set here

	g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
	g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	
	g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
	g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
	g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

	//Create the font
	D3DXCreateFontIndirect(g_pd3dDevice, &FONTDESC, &g_font);

	//---------------------------------------------------------------------------
	//Create DirectX objects
	//==== Load in our shader:
	LPD3DXBUFFER pErrors = NULL;
	//wchar_t *str1 = L"CubeShader.fx";
	DWORD dwShaderFlags = 0;
	//Create The First Shader
	if (FAILED(D3DXCreateEffectFromFile( g_pd3dDevice, "DefaultShader.fx", NULL, NULL, dwShaderFlags, NULL, &g_CubeShader, &pErrors ) ))
	{
		if (pErrors)
		{
			char *errorString = (char*)pErrors->GetBufferPointer();
			printf(errorString);
		}
	 
		return E_FAIL;
	}

    return S_OK;
}

void SetUpMatracies()
{
	//Set up some default view and projection matricies
    D3DXMatrixIdentity( &g_WorldViewProj );

	D3DXMATRIXA16 matWorld;
    D3DXMatrixIdentity( &matWorld );
    g_pd3dDevice->SetTransform( D3DTS_WORLD,  &matWorld );

    //Thinking the EyePt should be set to the player you are contoling's position (while in game)
	//Maybe the world has pointer to the entity being contolled? 
	//D3DXVECTOR3 EyePt(ControledPlayer.x, ControledPlayer.y + Offest, ControledPlayer.z);
	D3DXVECTOR3 EyePt(0.0f, 15.0f, -60.0f);//Defaulting to some value
	//Just look straight ahead of your Directional Vector (of the controlled player) 
    //D3DXVECTOR3 LookatPt( DirectionalVector.x, DirectionalVector.y, DirectionalVector.z);
	D3DXVECTOR3 LookatPt( 0.0f, 0.0f, 0.0f);//Defaulting to Straight ahead for now
    D3DXVECTOR3 UpVec( 0.0f, 1.0f, 0.0f );
    D3DXMATRIXA16 matView;
    D3DXMatrixLookAtLH( &matView, &EyePt, &LookatPt, &UpVec );

    //Set the Matrix Stack, View
	MatrixStack::ReturnInstance()->SetViewMatrix(matView);
	
    D3DXMATRIXA16 matProj;
    D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1280.0f / 720.0f, 1.0f, 1000.0f );
	MatrixStack::ReturnInstance()->SetProjectionMatrix(matProj);//Set the Matrix Stack, Projection

	//=== Multiply the world, view and projection matrices and set the shader variable!!
	D3DXMATRIXA16 worldViewProjection = matWorld * matView * matProj;
	g_CubeShader->SetMatrix("g_mWorldViewProjection", &worldViewProjection);

	g_WorldViewProj = worldViewProjection;
}

void Render()
{
    // Clear the backbuffer to a blue color
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 222, 0 ), 1.0f, 0 );

    // Begin the scene
    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
		World::Get().RenderObjects();

		// End the scene
        g_pd3dDevice->EndScene();
	}

    // Present the backbuffer contents to the display
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );

	//Need to add CleanUp(); when required
}